package com.android.love;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.StrictMode;

import com.android.love.ui.HomeActivity;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.MemoryCacheAware;
import com.nostra13.universalimageloader.cache.memory.impl.LRULimitedMemoryCache;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.utils.StorageUtils;

public class MyApplication extends Application {
	private final List<Activity> activityList = new LinkedList<Activity>();
	private static MyApplication instance;
	public static File cacheDir;

	private int defaultIndex = 6;

	// 保存活动实例的弱映射
	private HashMap<String, WeakReference<Context>> contextObjects = new HashMap<String, WeakReference<Context>>();

	@SuppressLint("NewApi")
	@Override
	public void onCreate() {
		super.onCreate();
		instance = this;
		// enableStrictMode();
		initImageLoader(getApplicationContext());
//		// 异常处理，不需要处理时注释掉这两句即可！
//		CrashHandler crashHandler = CrashHandler.getInstance();
//		// 注册crashHandler
//		crashHandler.init(getApplicationContext());
	}

	public int getDefaultIndex() {
		return defaultIndex;
	}

	public void setDefaultIndex(int defaultIndex) {
		this.defaultIndex = defaultIndex;
	}

	/**
	 * 单例模式中获取唯一的MyApplication实例
	 * 
	 * @return
	 */
	public static MyApplication getInstance() {
		if (null == instance) {
			instance = new MyApplication();
		}
		return instance;
	}

	/**
	 * 添加Activity到容器中
	 * 
	 * @param activity
	 */
	public void addActivity(Activity activity) {
		activityList.add(activity);
	}

	/**
	 * 遍历所有Activity并finish
	 */
	public void exit() {
		for (Activity activity : activityList) {

			if (activity != null) {
				if (!activity.isFinishing()) {
					activity.finish();
					// android.os.Process.killProcess(android.os.Process.myPid());
				}

				activity = null;
			}

			activityList.remove(activity);
		}
	}

	/**
	 * 开启StrictMode
	 */
	@SuppressLint("NewApi")
	public static void enableStrictMode() {
		if (hasGingerbread() && BuildConfig.DEBUG) {
			StrictMode.ThreadPolicy.Builder threadPolicyBuilder = new StrictMode.ThreadPolicy.Builder()
					.detectAll().penaltyLog();
			StrictMode.VmPolicy.Builder vmPolicyBuilder = new StrictMode.VmPolicy.Builder()
					.detectAll().penaltyLog();

			if (hasHoneycomb()) {
				threadPolicyBuilder.penaltyFlashScreen();
				vmPolicyBuilder.setClassInstanceLimit(HomeActivity.class, 1)
						.setClassInstanceLimit(HomeActivity.class, 1);
			}
			StrictMode.setThreadPolicy(threadPolicyBuilder.build());
			StrictMode.setVmPolicy(vmPolicyBuilder.build());
		}
	}

	public static boolean hasFroyo() {
		// Can use static final constants like FROYO, declared in later versions
		// of the OS since they are inlined at compile time. This is guaranteed
		// behavior.
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
	}

	public static boolean hasGingerbread() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
	}

	public static boolean hasHoneycomb() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
	}

	public static boolean hasHoneycombMR1() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1;
	}

	public static boolean hasJellyBean() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
	}

	/**
	 * 获取活动实例
	 * 
	 * @param className
	 * @return
	 */
	public synchronized Context getActiveContext(String className) {
		WeakReference<Context> ref = contextObjects.get(className);
		if (ref == null) {
			return null;
		}

		final Context c = ref.get();
		if (c == null) // 如果弱引用已经失效，确保移除它
			contextObjects.remove(className);

		return c;
	}

	/**
	 * 添加活动实例
	 * 
	 * @param className
	 * @return
	 */
	public synchronized void setActiveContext(String className, Context context) {
		WeakReference<Context> ref = new WeakReference<Context>(context);
		this.contextObjects.put(className, ref);
	}

	/**
	 * 移除活动实例
	 * 
	 * @param className
	 * @return
	 */
	public synchronized void resetActiveContext(String className) {
		contextObjects.remove(className);
	}

	/**
	 * <p>
	 * Invoked if the application is about to close. Application close is being
	 * defined as the transition of the last running Activity of the current
	 * application to the Android home screen using the BACK button. You can
	 * leverage this method to perform cleanup logic such as freeing resources
	 * whenever your user "exits" your app using the back button.
	 * </p>
	 * <p>
	 * Note that you must not rely on this callback as a general purpose "exit"
	 * handler, since Android does not give any guarantees as to when exactly
	 * the process hosting an application is being terminated. In other words,
	 * your application can be terminated at any point in time, in which case
	 * this method will NOT be invoked.
	 * </p>
	 */
	public void onClose() {
		// NO-OP by default
	}

	/**
	 * 初始化ImageLoader
	 * 
	 * @param context
	 */
	public static void initImageLoader(Context context) {
		cacheDir = StorageUtils.getCacheDirectory(context);
		// 内存缓存取应用最大内存的1/8
		int memoryCacheSize = (int) (Runtime.getRuntime().maxMemory() / 8);
		MemoryCacheAware<String, Bitmap> memoryCache;
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
			memoryCache = new LruMemoryCache(memoryCacheSize);
		} else {
			memoryCache = new LRULimitedMemoryCache(memoryCacheSize);
		}

		// This configuration tuning is custom. You can tune every option, you
		// may tune some of them,
		// or you can create default configuration by
		// ImageLoaderConfiguration.createDefault(this);
		// method.
		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				context).threadPriority(Thread.MIN_PRIORITY)
				.memoryCache(memoryCache)
				// .memoryCache(new WeakMemoryCache())
				// .denyCacheImageMultipleSizesInMemory()
				.discCache(new UnlimitedDiscCache(cacheDir))
				// .discCacheExtraOptions(0, 0, Bitmap.CompressFormat.JPEG, 60)
				.discCacheSize(50 * 1024 * 1024).discCacheFileCount(100)
				// .discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75)
				.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
				// .tasksProcessingOrder(QueueProcessingType.LIFO).enableLogging()
				// .offOutOfMemoryHandling()
				// .discCache(new UnlimitedDiscCache("/mnt", new
				// Md5FileNameGenerator()))
				.build();
		// Initialize ImageLoader with configuration.
		ImageLoader.getInstance().init(config);
	}
}
